import { ref, Ref, defineComponent, computed, watch } from 'vue';
import {
  getDropdownProps,
  getEditorEmits,
  useNamespace,
} from '@ibiz-template/vue3-util';
import './ibiz-dropdown.scss';
import { DropDownListEditorController } from '../dropdown-list-editor.controller';

export const IBizDropdown = defineComponent({
  name: 'IBizDropdown',
  props: getDropdownProps<DropDownListEditorController>(),
  emits: getEditorEmits(),
  setup(props, { emit }) {
    const ns = useNamespace('dropdown');
    const c = props.controller;

    const items: Ref<readonly IData[]> = ref([]);

    // 是否是树形
    const hasChildren = ref(false);

    // 树数据
    const treeNodes: Ref<IData[]> = ref([]);

    // 样式变量
    const cssVars = computed(() => {
      if (c.model.editorType === 'DROPDOWNLIST_100') {
        return ns.cssVarBlock({ width: `100px` });
      }
      return {};
    });

    // 处理树数据
    const handleTreeNodes = (nodes: readonly IData[]) => {
      if (nodes.length === 0) {
        return [];
      }
      const list: IData[] = [];
      nodes.forEach((codeItem: IData) => {
        const tempObj: IData = {
          label: codeItem.text,
          value: codeItem.value,
          children: [],
        };
        if (codeItem.children && codeItem.children.length > 0) {
          tempObj.children = handleTreeNodes(codeItem.children);
        }
        list.push(tempObj);
      });
      return list;
    };

    c.loadCodeList(props.data!).then((codeList: readonly IData[]) => {
      items.value = codeList;
      for (let i = 0; i < items.value.length; i++) {
        const _item = items.value[i];
        if (_item.children) {
          hasChildren.value = true;
          treeNodes.value = handleTreeNodes(codeList);
          break;
        }
      }
    });

    // 当前值
    const curValue: Ref<Array<string> | string | undefined> = computed({
      get() {
        if (props.value) {
          return c!.multiple ? props.value?.split(',') : props.value;
        }
        return props.value;
      },
      set(select: string | Array<string> | undefined) {
        if (Array.isArray(select)) {
          emit('change', select.length === 0 ? null : select.join(','));
        } else {
          emit('change', select);
        }
      },
    });

    const valueText = computed(() => {
      const valueArr = Array.isArray(curValue.value)
        ? curValue.value
        : [curValue.value];

      return items.value
        .filter(item => valueArr.includes(item.value))
        .map(item => item.text)
        .join(',');
    });

    // 自动聚焦
    const editorRef = ref();
    if (props.autoFocus) {
      watch(editorRef, newVal => {
        if (newVal) {
          newVal.focus();
        }
      });
    }
    const onFocus = () => {
      emit('focus');
    };
    const onBlur = () => {
      setTimeout(() => {
        emit('blur');
      }, 100);
    };

    return {
      ns,
      c,
      curValue,
      items,
      valueText,
      hasChildren,
      onBlur,
      onFocus,
      editorRef,
      treeNodes,
      cssVars,
    };
  },

  render() {
    // 编辑态内容
    const editContent = this.hasChildren ? (
      <el-tree-select
        v-model={this.curValue}
        clearable
        data={this.treeNodes}
        check-strictly
        render-after-expand={false}
        multiple={this.c.multiple}
        placeholder={this.c.placeHolder ? this.c.placeHolder : ' '}
        disabled={this.disabled}
      />
    ) : (
      <el-select
        ref='editorRef'
        v-model={this.curValue}
        clearable
        class={[this.ns.e('select')]}
        multiple={this.c.multiple}
        placeholder={this.c.placeHolder ? this.c.placeHolder : ' '}
        disabled={this.disabled}
        onBlur={this.onBlur}
        onFocus={this.onFocus}
      >
        {this.items.map(item => {
          return <el-option value={item.value} label={item.text}></el-option>;
        })}
      </el-select>
    );
    return (
      <div
        class={[
          this.ns.b(),
          this.disabled ? this.ns.m('disabled') : '',
          this.readonly ? this.ns.m('readonly') : '',
        ]}
        style={this.cssVars}
      >
        {this.readonly ? this.valueText : editContent}
      </div>
    );
  },
});
